﻿using Knife.Core.Attributes;
using Knife.Core.Exception;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Knife.Core.Model
{
    public class MapperEntity
    {
        public Type EnityType { set; get; }
        public string MapTableName { set; get; }
        public string MapTableID { set; get; }
        public List<PropertyInfo> PropertyList { set; get; }
        public Dictionary<PropertyInfo, string> ColumnMapDic { set; get; }
        public List<string> IgnoreFieldList { set; get; }

        public MapperEntity(Type EnityType)
        {
            this.EnityType = EnityType;
            IgnoreFieldList = new List<string>();
            ColumnMapDic = new Dictionary<PropertyInfo, string>();
        }

        public void ScanSelf()
        {
            PropertyList = new List<PropertyInfo>(EnityType.GetProperties());
            //获取映射表名
            TableName TableAttribute = (TableName)EnityType.GetCustomAttribute(typeof(TableName));
            if (TableAttribute == null)
            {
                MapTableName = EnityType.Name;
            }
            else
            {
                MapTableName = TableAttribute.Name;
            }
            //获取映射主键名
            List<PropertyInfo> KeyPropertyInfoList = PropertyList.FindAll((PropertyInfo p) => p.GetCustomAttribute(typeof(TableID)) != null);
            if (KeyPropertyInfoList.Count == 0)
            {
                throw new LostTableIDException(string.Format("实体映射类{0}未指定主键字段", EnityType.FullName));
            }
            else if (KeyPropertyInfoList.Count == 1)
            {
                PropertyInfo KeyPropertyInfo = KeyPropertyInfoList[0];
                TableField ColumnAttribute = (TableField)KeyPropertyInfo.GetCustomAttribute(typeof(TableField));
                if (ColumnAttribute == null)
                {
                    MapTableID = KeyPropertyInfo.Name;
                }
                else
                {
                    MapTableID = ColumnAttribute.Name;
                    if (string.IsNullOrEmpty(MapTableID))
                    {
                        throw new LostTableFieldException(string.Format("实体映射类{0}中的{1}字段声明了Column注解，未指定列名称", EnityType.FullName, KeyPropertyInfo.Name));
                    }
                }
            }
            else
            {
                throw new RepeaTableIDException(string.Format("实体映射类{0}定义不止一个主键字段", EnityType.FullName));
            }
            //获取映射列
            foreach (PropertyInfo PropertyItem in PropertyList)
            {
                Ignore IgnoreAttribute = (Ignore)PropertyItem.GetCustomAttribute(typeof(Ignore));
                if (IgnoreAttribute == null)
                {
                    string ColumnName = string.Empty;
                    TableField ColumnAttribute = (TableField)PropertyItem.GetCustomAttribute(typeof(TableField));
                    if (ColumnAttribute != null)
                    {
                        ColumnName = ColumnAttribute.Name;
                    }
                    else
                    {
                        ColumnName = PropertyItem.Name;
                    }

                    if (!string.IsNullOrEmpty(ColumnName))
                    {
                        if (ColumnMapDic.ContainsValue(ColumnName))
                        {
                            throw new RepeaTableFieldException(string.Format("实体映射类{0}定义的属性名称或Column注解中有重复的列{1}", EnityType.FullName, ColumnName));
                        }
                        else
                        {
                            ColumnMapDic.Add(PropertyItem, ColumnName);
                        }
                    }
                    else
                    {
                        throw new LostTableFieldException(string.Format("实体映射类{0}中的{1}字段声明了Column注解，未指定列名称", EnityType.FullName, PropertyItem.Name));
                    }
                }
                else
                {
                    IgnoreFieldList.Add(PropertyItem.Name);
                }
            }

        }
    }
}
